package Listening;

import java.io.File;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.ArrayList;
import java.util.Iterator;

import org.eclipse.swt.widgets.ProgressBar;

import UI.OurGUI;

import Commnads.ListenCommands;

/**
 * The Tagger is a Thread that executing the initialization thread.
 * First we counting the number of all files in all listened directories,
 * and then tagging the files, and updating the {@link ProgressBar} respectively.
 * @author DROR
 */
public class Tagger extends Thread 
{
	private boolean startInit;
	private boolean pause;
	private int counter;
	private int numOfAllFiles;
	private ListenCommands listenCommands;
	private Object obj;

	public Tagger(){}

	/**
	 * Constructor
	 * @param listencommands reference of class {@link ListenCommands} 
	 */
	public Tagger(ListenCommands listencommands) 
	{
		listenCommands= listencommands;
		this.startInit = false;
		this.pause = false;
		counter=0;
		numOfAllFiles=0;
		obj = new Object();
	}

	/**
	 * This function checking if initialization thread had started
	 * @return  {@link Boolean} If the initialization thread has working
	 */
	public boolean getStartInit() {
		return startInit;
	}

	/**
	 * This function sets the flag  that tell us if the initialization thread had started
	 * @param {@link Boolean} flag true or false
	 */
	public void setStartInit(boolean flag) {
		this.startInit = flag;
	}

	/**
	 * This function checking if initialization thread had paused
	 * @return {@link Boolean} If the initialization thread has working
	 */
	public boolean isPause() {
		return pause;
	}

	/**
	 * This function running as thread, and tagging automatically all the files in the
	 * selected directories.
	 * for each file that had tagged, we updated the {@link ProgressBar} from here. 
	 */
	public void run() 
	{
		ArrayList<String> dirs = new ArrayList<String>();
		ArrayList<String> dirsOnListen = listenCommands.getDirectories();
		/* checking if we have directories in DB */ 
		if (dirsOnListen != null)
		{
			dirs.addAll(dirsOnListen);
			Iterator<String> it = dirs.iterator();
			/* counting all the files in all directories */
			while (it.hasNext())
			{
				String path = it.next();
				File file = new File(path);
				numOfAllFiles += countFilesInDirectory(file);	
			}
			/* moving through the directories, and tagging all the files there */
			Iterator<String> iter = dirs.iterator();
			while (iter.hasNext())
			{
				String path = iter.next();
				Path p = Paths.get(path);
				try{
					Files.walkFileTree(p, new SimpleFileVisitor<Path>() {
						public FileVisitResult visitFile(Path dir, BasicFileAttributes attr)  
						{
							if (startInit) 	/* the can do the initialization */
								if (pause) 	/*  we need pause the initialization */
								{
									synchronized (obj) {
										try {
											obj.wait();
										} 
										catch (InterruptedException e) {e.printStackTrace();}
									}
								}
							File file = new File(dir.toString());
							if (!startInit)  /*  we need stop the initialization */
							{
								OurGUI.update(0); /* initializing the progress bar*/
								return null;
							}
							/* checking if we catch a file */
							if (file.isFile())
							{
								counter++;
								String f= dir.toString();
								listenCommands.autoTag(f); /* tagging the file */
								OurGUI.update(getPercent());
							}
							return FileVisitResult.CONTINUE;
						}
					});
				}
				catch (NullPointerException e) {}
				if (numOfAllFiles==counter)
					startInit=false;
			}
		}
	}

	/**
	 * This function calculate the percent of the tagged files for updating the {@link ProgressBar} 
	 * @return The percent
	 */
	public int getPercent()
	{
		int percent = (int) ((double)counter/(double)numOfAllFiles*(double)100);
		return percent;
	}

	/**
	 * This function sets pause flag that tell us if the initialization thread had paused.
	 */
	public void pauseInit()
	{
		pause= true;
	}

	/**
	 * This function sets pause flag that tell us if the initialization thread had resumed.
	 */
	public void resumeInit()
	{
		pause= false;
		synchronized (obj) {
			obj.notify();
		}
	}

	/**
	 * This is a recursive function counting the number of files in directory
	 * @param directory a  {@link File} belong to listened directory
	 * @return the number of files in directory
	 */
	public static int countFilesInDirectory(File directory) 
	{
		int count = 0;
			for (File file : directory.listFiles()) {
				if (file.isFile()) {
					count++;
				}
				if (file.isDirectory()) {
					count += countFilesInDirectory(file);
				}
			}
		return count;
	}
}
